
#include <promote/TimeUtils.hpp>

#include "ExpiryCalculator.hpp"

using namespace provident;

ExpiryCalculator::ExpiryCalculator(ExpiryCalculator::Type const type,
                                   promote::Timestamp const& timestamp)
:   _type(type),
    _startMonth(timestamp.month()),
    _startDay(timestamp.dayOfMonth()),
    _startYear(timestamp.year())
{
}

ExpiryCalculator::ExpiryCalculator(ExpiryCalculator::Type const type,
                                   unsigned const startMonth,
                                   unsigned const startDay,
                                   unsigned const startYear)
:   _type(type),
    _startMonth(startMonth),
    _startDay(startDay),
    _startYear(startYear)
{
}

double
ExpiryCalculator::yearsTilExpiry(unsigned const month,
                                 unsigned const day,
                                 unsigned const year)
{
    // Check history first
    unsigned const key(createKey(month,day,year));
    double* resultPtr;
    if( _history.find(key,resultPtr) ) {
        return *resultPtr;
    }

    // Calculate
    double result;
    if( _type == CALENDAR_YEAR ) {
        promote::Timestamp timestamp;
        timestamp.date(_startMonth, _startDay, _startYear);
        result = -static_cast<int>(timestamp.dayOfYear()) / (timestamp.isLeapYear() ? 366.0 : 365.0);
        for(unsigned y = timestamp.year(); y != year; ++y) {
            result += 1.0;
        }
        timestamp.date(month, day, year);
        result += (timestamp.dayOfYear() - 1) / (timestamp.isLeapYear() ? 366.0 : 365.0);
    } else {
        result = 0.0;
    }

    // Save to history, then return
    _history[key] = result;
    return result;
}

